[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[OPTIMIZE 1]
[OPTION 1]
[BITS 32]
	EXTERN	_io_hlt
	EXTERN	_io_load_eflags
	EXTERN	_io_cli
	EXTERN	_io_out8
	EXTERN	_io_store_eflags
[FILE "bootpack.c"]
[SECTION .text]
	GLOBAL	_HariMain
_HariMain:
	PUSH	EBP			; 将上个栈帧地址放到当前栈帧的基位置，其实就是*esp=ebp;esp++;
	MOV	EBP,ESP			; 将当前栈帧寄存器存储当前栈帧地址，其实就是ebp=esp; 构成了一个链表：ebp->当前栈帧基地址->上一个栈帧基地址...的单向链表。
	CALL	_init_palette
	PUSH	171
	PUSH	319
	PUSH	0
	PUSH	0
	PUSH	14
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	172
	PUSH	319
	PUSH	172
	PUSH	0
	PUSH	8
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56			; 调用两次_boxfill8之后才清理一次所以就是7（参数个数）*4（intsize）*2
	PUSH	173
	PUSH	319
	PUSH	173
	PUSH	0
	PUSH	7
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	199
	PUSH	319
	PUSH	174
	PUSH	0
	PUSH	8
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
	PUSH	176
	PUSH	59
	PUSH	176
	PUSH	3
	PUSH	7
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	196
	PUSH	2
	PUSH	176
	PUSH	2
	PUSH	7
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
	PUSH	196
	PUSH	59
	PUSH	196
	PUSH	3
	PUSH	15
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	195
	PUSH	59
	PUSH	177
	PUSH	59
	PUSH	15
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
	PUSH	197
	PUSH	59
	PUSH	197
	PUSH	2
	PUSH	0
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	197
	PUSH	60
	PUSH	176
	PUSH	60
	PUSH	0
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
	PUSH	176
	PUSH	316
	PUSH	176
	PUSH	273
	PUSH	15
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	196
	PUSH	273
	PUSH	177
	PUSH	273
	PUSH	15
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
	PUSH	197
	PUSH	316
	PUSH	197
	PUSH	273
	PUSH	7
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	PUSH	197
	PUSH	317
	PUSH	176
	PUSH	317
	PUSH	7
	PUSH	320
	PUSH	655360
	CALL	_boxfill8
	ADD	ESP,56
L2:
	CALL	_io_hlt
	JMP	L2				; 直接跳到L2进行循环
[SECTION .data]			; 数据区虽然被作为hrb的最后部分，但是仍然需要将此区域复制到固定位置即0x310000，因为代码中对数据区的引用在obj链接的时候已经设定为了0x310000; 具体原因需要编译obj2bim来进行分析
_table_rgb.0:
	DB	0
	DB	0
	DB	0
	DB	-1
	DB	0
	DB	0
	DB	0
	DB	-1
	DB	0
	DB	-1
	DB	-1
	DB	0
	DB	0
	DB	0
	DB	-1
	DB	-1
	DB	0
	DB	-1
	DB	0
	DB	-1
	DB	-1
	DB	-1
	DB	-1
	DB	-1
	DB	-58
	DB	-58
	DB	-58
	DB	-124
	DB	0
	DB	0
	DB	0
	DB	-124
	DB	0
	DB	-124
	DB	-124
	DB	0
	DB	0
	DB	0
	DB	-124
	DB	-124
	DB	0
	DB	-124
	DB	0
	DB	-124
	DB	-124
	DB	-124
	DB	-124
	DB	-124
[SECTION .text]
	GLOBAL	_init_palette
_init_palette:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	_table_rgb.0
	PUSH	15
	PUSH	0
	CALL	_set_palette
	LEAVE				; leave表示清理堆栈中的参数部分，即将esp设定为ebp（即删除当前栈帧的基地址），同时将栈帧基地址的数据pop到ebp（即恢复上一个栈帧ebp的指针寄存器）
	RET
	GLOBAL	_set_palette
_set_palette:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	EDI
	PUSH	ESI
	PUSH	EBX
	PUSH	ECX
	MOV	EBX,DWORD [8+EBP]		; EBP指向的是上一个栈帧基地址，+4指向的是返回地址，+8是第一个参数地址...
	MOV	EDI,DWORD [12+EBP]
	MOV	ESI,DWORD [16+EBP]
	CALL	_io_load_eflags
	MOV	DWORD [-16+EBP],EAX
	CALL	_io_cli
	PUSH	EBX
	PUSH	968
	CALL	_io_out8
	CMP	EBX,EDI
	POP	EAX
	POP	EDX
	JLE	L11
L13:
	MOV	EAX,DWORD [-16+EBP]
	MOV	DWORD [8+EBP],EAX
	LEA	ESP,DWORD [-12+EBP]
	POP	EBX
	POP	ESI
	POP	EDI
	POP	EBP
	JMP	_io_store_eflags		; 没有RET，而是用JMP替代，等于将_io_store_eflags代码内联了一样，直接用_io_store_eflags的RET语句来返回两层函数调用
L11:
	MOV	AL,BYTE [ESI]
	INC	EBX
	SHR	AL,2				; SHR是右移操作，移动2位bit。SHL是左移。
	MOVZX	EAX,AL			; MOVZX是赋值并将其余部位置为0，类似c语言向上转型
	PUSH	EAX
	PUSH	969
	CALL	_io_out8
	MOV	AL,BYTE [1+ESI]
	SHR	AL,2
	MOVZX	EAX,AL
	PUSH	EAX
	PUSH	969
	CALL	_io_out8
	MOV	AL,BYTE [2+ESI]
	SHR	AL,2
	ADD	ESI,3
	MOVZX	EAX,AL
	PUSH	EAX
	PUSH	969
	CALL	_io_out8
	ADD	ESP,24
	CMP	EBX,EDI
	JLE	L11
	JMP	L13
	GLOBAL	_boxfill8
_boxfill8:
	PUSH	EBP
	MOV	EBP,ESP
	PUSH	EDI
	PUSH	ESI
	PUSH	EBX
	PUSH	EDI
	PUSH	EDI
	MOV	AL,BYTE [16+EBP]
	MOV	ECX,DWORD [24+EBP]
	MOV	EDI,DWORD [28+EBP]
	MOV	BYTE [-13+EBP],AL
	CMP	ECX,DWORD [32+EBP]
	JG	L26
	MOV	EBX,DWORD [12+EBP]
	IMUL	EBX,ECX
L24:
	MOV	EDX,DWORD [20+EBP]
	CMP	EDX,EDI
	JG	L28
	MOV	ESI,DWORD [8+EBP]
	ADD	ESI,EBX
	ADD	ESI,EDX
	MOV	DWORD [-20+EBP],ESI
L23:
	MOV	ESI,DWORD [-20+EBP]
	MOV	AL,BYTE [-13+EBP]
	INC	EDX
	MOV	BYTE [ESI],AL
	INC	ESI
	MOV	DWORD [-20+EBP],ESI
	CMP	EDX,EDI
	JLE	L23
L28:
	INC	ECX
	ADD	EBX,DWORD [12+EBP]
	CMP	ECX,DWORD [32+EBP]
	JLE	L24
L26:
	POP	EBX
	POP	ESI
	POP	EBX
	POP	ESI
	POP	EDI
	POP	EBP
	RET
